/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __PACT_NODEHANDLER_HDR__
#define __PACT_NODEHANDLER_HDR__

#ifdef WIN32
	// disable - decorated name length exceeded
	#pragma warning(disable:4503)
	// disable 'identifier' truncation warning
	#pragma warning(disable:4786)
#endif


#include <stdexcept>

#include "conflictdeclaration.h"
#include "document.h"
#include "score.h"
//Added by qt3to4:
#include <Q3BoxLayout>


// Qt classes
class Q3BoxLayout;
class QObject;
class QWidget;

// \todo
// \todo refactor
// \todo

// node handlers should be functors (pass by value) and processing of 
// child nodes should use for_each algoritum

//

namespace pact {

	class TrialTask;


	/*!
	 * \struct pact::nodehandler_error
	 */
	struct nodehandler_error : public std::runtime_error{
		nodehandler_error(const std::string& msg) 
			:std::runtime_error(msg){}
	};


	/*!
	 * \struct pact::InputNodeHandler
	 */
	struct InputNodeHandler : xml::NodeHandler {
		
		InputNodeHandler( const xml::Document *doc, xml::DocumentView * view )
				: NodeHandler( doc, view )
		{}

		void operator()( const xml::DocumentNode * );
		QWidget* process( const xml::DocumentNode *, QWidget * );

	};


	/*!
	 * \struct pact::InputNodeHandler
	 */
	struct DisplayNodeHandler : xml::NodeHandler {
		
		DisplayNodeHandler( const xml::Document *doc, xml::DocumentView * view )
				: NodeHandler( doc, view )
		{}

		void operator()( const xml::DocumentNode * );
		QWidget* process( const xml::DocumentNode *, QWidget * );
	};

	/*!
	 * \struct pact::FeedbackNodeHandler
	 */
	struct FeedbackNodeHandler : xml::NodeHandler 
	{
		FeedbackNodeHandler(const xml::Document* a_doc, xml::DocumentView* a_view)
			: NodeHandler(a_doc, a_view)
		{
		}

		void operator()( const xml::DocumentNode *);
		QWidget* process( const xml::DocumentNode *, QWidget *);
	};

	/*!
	 * \struct pact::InstructionNodeHandler
	 */
	struct InstructionNodeHandler : xml::NodeHandler 
	{
		InstructionNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};


	/*!
	 * \struct pact::MultiQuestionNodeHandler
	 */
	struct MultiQuestionNodeHandler : xml::NodeHandler 
	{
		MultiQuestionNodeHandler(
				const xml::Document* doc, 
				xml::DocumentView* view
		)
			:NodeHandler( doc, view )
		{}

		void operator()( const xml::DocumentNode * );
	};


	/*!
	 * \struct pact::QuestionNodeHandler
	 */
	struct QuestionNodeHandler : xml::NodeHandler 
	{
		QuestionNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};

	/*!
	 * \struct pact::ParamNodeHandler
	 */
	struct ParamNodeHandler : xml::NodeHandler 
	{
		ParamNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};

	/*!
	 *
	 */
	struct ColourNodeHandler : xml::NodeHandler {
		ColourNodeHandler( const xml::Document *doc, xml::DocumentView *view )
				: NodeHandler(doc, view) {};
		void operator()( const xml::DocumentNode * );
	};

	struct FeedbackGoalNodeHandler : xml::NodeHandler
	{
		FeedbackGoalNodeHandler(const xml::Document* a_doc, xml::DocumentView* a_view)
			: NodeHandler(a_doc, a_view)
		{
		};

		void operator() (const xml::DocumentNode* a_node);
	};

	/*!
	 *
	 */
	struct InfoBlockNodeHandler : xml::NodeHandler {
		InfoBlockNodeHandler( const xml::Document *doc, xml::DocumentView *view )
				: NodeHandler(doc, view) {};
		void operator()( const xml::DocumentNode * );
	};

	struct AircraftDeclarationNodeHandler : xml::NodeHandler
	{
		AircraftDeclarationNodeHandler( const xml::Document* doc, 
										xml::DocumentView* view)
				: NodeHandler(doc, view) 
		{
		};

		void operator()(const xml::DocumentNode* a_node);
	};

	/*!
	 *
	 */
	struct ToolsNodeHandler : xml::NodeHandler {
		ToolsNodeHandler( const xml::Document *doc, xml::DocumentView *view )
				: NodeHandler(doc, view) {};
		void operator()( const xml::DocumentNode * );
	};

	struct AltitudeNodeHandler : xml::NodeHandler 
	{
		AltitudeNodeHandler(const xml::Document* doc, xml::DocumentView* view)
				: NodeHandler(doc, view) 
		{
		};

		void operator()( const xml::DocumentNode *);
	};

	/*!
	 *
	 */
	struct KeysNodeHandler : xml::NodeHandler {
		KeysNodeHandler( const xml::Document *doc, xml::DocumentView *view )
				: NodeHandler(doc, view) {};
		void operator()( const xml::DocumentNode * );
	};


	/*!
	 *
	 */
	struct InitialToolsNodeHandler : xml::NodeHandler {
		InitialToolsNodeHandler( const xml::Document *doc, xml::DocumentView *view )
			: NodeHandler(doc, view) {};
		void operator()( const xml::DocumentNode * );
	};


	/*!
	 *
	 */
	class ScoringNodeHandler : public xml::NodeHandler {
	public:
		ScoringNodeHandler( const xml::Document *, xml::DocumentView * );
		~ScoringNodeHandler();

		void operator()( const xml::DocumentNode* );
		void done();

	private:
		void set_score( 
				const xml::DocumentNode *, 
				atc::ScoreBuilder* (atc::ScoreBuilder::*)(int) 
			);
		void set_audio( 
				const xml::DocumentNode *, 
				atc::ScoreBuilder* (atc::ScoreBuilder::*)(const std::string&, int) 
			);

		void
		SetDelay(	const xml::DocumentNode* node,
					atc::ScoreBuilder* (atc::ScoreBuilder::*delay)(int));

		void
		SetReference(	const xml::DocumentNode* a_node,
						std::string a_event,
						atc::ScoreBuilder* (atc::ScoreBuilder::*)(const std::string&, const std::string&));

	private:
		atc::ScoreBuilder _builder;
	};


	/*!
	 * \struct pact::TrialNodeHandler
	 */
	struct TrialNodeHandler : xml::NodeHandler 
	{
		TrialNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};

	/*!
	 * \struct pact::MapNodeHandler
	 */
	struct MapNodeHandler : xml::NodeHandler 
	{
		MapNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};


	/*!
	 * \class pact::MapRouteNodeHandler
	 */
	class MapRouteNodeHandler : public xml::NodeHandler 
	{
	public:

		MapRouteNodeHandler(
			const xml::Document*, 
			xml::DocumentView*,
			const xml::DocumentNode*
		);
		~MapRouteNodeHandler();

		void operator()(const xml::DocumentNode*);

	private:

		std::string _routeID;

	};


	/*!
	 * \class pact::MapSectorNodeHandler
	 */
	class MapSectorNodeHandler : public xml::NodeHandler 
	{
	public:

		MapSectorNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view,
			const xml::DocumentNode*
		);
		~MapSectorNodeHandler();

		void operator()(const xml::DocumentNode*);

	private:

		std::string _sectorID;

	};


	/*!
	 * \struct pact::SkyNodeHandler
	 */
	struct SkyNodeHandler : xml::NodeHandler 
	{
		SkyNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};


	/*!
	 * \struct pact::SkyAircraftNodeHandler
	 */
	struct SkyAircraftNodeHandler : xml::NodeHandler 
	{
		SkyAircraftNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};


	/*!
	 * \struct pact::SkyAircraftFlightpathNodeHandler
	 */
	struct SkyAircraftFlightpathNodeHandler : xml::NodeHandler 
	{
		SkyAircraftFlightpathNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
	};


	/*!
	 * Decode "area" node (eg weather or military)
	 */
	class AreaNodeHandler : public xml::NodeHandler 
	{
	public:

		AreaNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view,
			const xml::DocumentNode*
		);
		~AreaNodeHandler();

		void operator()( const xml::DocumentNode* );

	private:

		std::string _areaID;

	};


	class AircraftStatusNodeHandler : public xml::NodeHandler 
	{
	public:
		AircraftStatusNodeHandler(	const xml::Document*, 
									xml::DocumentView*, 
									const xml::DocumentNode*);
		~AircraftStatusNodeHandler();

		void operator()(const xml::DocumentNode*);
		void done();

	private:
		atc::ConflictDeclarationBuilder m_builder;
	};


	/*!
	 * \struct pact::UINodeHandler
	 */
	struct UINodeHandler : xml::NodeHandler 
	{
		UINodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
		{}

		void operator()(const xml::DocumentNode*);
		void build_dialog( const xml::DocumentNode *, TrialTask * ); 
	};


	/*!
	 * \class pact::UIConnectionNodeHandler
	 */
	class UIConnectionNodeHandler : public xml::NodeHandler 
	{
	public:

		UIConnectionNodeHandler(
			const xml::Document* doc, 
			xml::DocumentView* view
		)
			:NodeHandler(doc, view)
			,_tx(0), _sig("")
			,_rx(0), _slot("")
		{}

		void operator()(const xml::DocumentNode*);

	private:

		QWidget* widget_ptr(const std::string&)const;
		void connect()const;

	private:

		QObject* _tx;
		std::string _sig;
		QObject* _rx;
		std::string _slot;

	};
};

#endif
